--
-- Author: shineflag
-- Date: 2017-02-15 17:13:09
--

local skynet = require("skynet")
local log = require("log")
local proto = require("json_proto")
local json = require("json")
local cluster = require "skynet.cluster"
local cts = require("constants")

local TAG = "USERAGENT"

skynet.register_protocol {
	name = "client",
	id = skynet.PTYPE_CLIENT,
	unpack = skynet.tostring,
}

local HEART_TIME = 20*100   --这么久没检测到心跳包，则认为掉线

local log_agent  --日志服务

local hall    --hall
local alloc   --配桌服务器

local mid 
local secret
local connected = false --玩家是否连接上

local last_heart_time = 0  --最近收到心跳包的时间


local heart_data = proto.create_resp("heart_beat")
local CMD = {}

local texas_tables = {}  --缓存桌子的handler
local uinfo = {--用户的一些基本信息
	-- "mnick",
	-- "icon" ,
	-- "sex",
	-- "mstatus",
	-- "mactivetime",
	-- "mentrydays",
	-- "version",
	-- "nettype",
	-- "pay",
	-- "inviteid",
} 
--玩家正在参加的现金桌 
local cashs = {
	--[tid] =  {lv=1, tid=1001, seatid=3},
}


local function heart_check()
	if connected then 
		local dif = skynet.now() - last_heart_time 
		if dif > HEART_TIME then 
			log.d(TAG, "user[%s] long time recv heart [%d]",mid, dif)
			skynet.send(hall, "lua", "socket_close",mid)
			connected = false
		end
	end
end

--获取某个场次下某个桌子的 hanlder
local function get_table_hanlder(lv, tid)
	
end

local function  get_uinfo(  )
	local uinfo_center = skynet.uniqueservice "uinfo"
	local ret, data = skynet.call(uinfo_center, "lua", "getuinfo", mid) 
	if ret then 
		log.d(TAG,"load user[%d] uinfo[%s]", mid, json.encode(data))
		return data
	else
		log.e(TAG, "load user[%d] uinfo failed",mid)
		return {}
	end
end



function CMD.login(source, id, secret)
	-- you may use secret to make a encrypted data stream
	log.d(TAG,"%s login  serect[%s]", id, secret)
	connected = true
	last_heart_time = skynet.now()	
	hall = source
	mid = id
	secret = secret

	--[[
	uinfo = get_uinfo()
	if not next(uinfo) then   --登录失败
		log.e(TAG,"mid[%s] login failed",id)
		local pkg = proto.create_resp("login.kick",{ret=200, msg = "login failed"})
		skynet.call(hall, "lua", "push", mid,pkg)	
		return false
	end
	]]

	return true
end

function CMD.logout()
	log.e(TAG,"useragent[%s] logout",mid)
	if hall then
		skynet.call(hall, "lua", "logout", mid)
	end
end

-- call by other service
function CMD.push( pkg)
	--log.d(TAG,"useragent[%s] push data:%d",mid,#pkg)
	if hall then
		return skynet.call(hall, "lua", "push", mid,pkg)
	end
	log.e(TAG,"not hall")
	return false
end

function CMD.afk()
	-- the connection is broken, but the user may back
	log.d(TAG, "user[%s] AFK",mid)
	connected = false
end


--call by other service 
function CMD.getuinfo()
	if not next(uinfo) then 
		uinfo = get_uinfo()
	end
	return uinfo
end


--call by halld  (client socket)
local  function do_request(data)
	--log.d(TAG,"mid[%d] do_request data[%s]", mid, data)
	local pkg = proto.unpack_body(data)

	if pkg.cmd == "heart_beat" then 
		--log.d(TAG,"heart_beat:%s",heart_data)
		last_heart_time = skynet.now()
		return heart_data 
	end

	log.d(TAG,"mid[%d] recv cmd[%s]",mid,pkg.cmd)

	local model, cmd = pkg.cmd:match("([^.]+).([^.]+)")

	if model == "texas" then
		local lv = pkg.req.lv
		local tid = pkg.req.tid 
		if cmd == "login" then
			texas_tables[tid] =  nil
		end
		local thanler = get_table_hanlder(lv, tid)
		if thanler then
			if cmd == "login" then
				return skynet.call(thanler,"lua",cmd,skynet.self(), mid,pkg.req)
			else
				return skynet.call(thanler,"lua",cmd, mid,pkg.req)
			end

		else
			log.e(TAG,"cmd[%s] not table handler",pkg.cmd)
			return proto.create_resp("texas.login",{ret = -101, lv = pkg.req.lv, tid=pkg.req.tid })
		end

	elseif model == "alloc" then 
		if cmd == "search" then 
			if next(cashs) then 
				for _, v in pairs(cashs) do 
					if pkg.req.lv == v.lv then 
						log.d(TAG,"user[%d] alloc.search cash lv[%d]  but found in tid[%d], seatid[%d]",mid, v.lv, v.tid, v.seatid)
						return proto.create_resp("alloc.search",{ret = 200, lv=v.lv, tid=v.tid})
					end
				end
			end
		end
		return skynet.call(alloc, "lua", cmd ,mid, data)
	else
		local service = skynet.uniqueservice(model)
		if service then
			return skynet.call(service, "lua", cmd ,mid, pkg.req)
		else
			log.e(TAG,"Unkow model[%s] command[%s]",model,cmd)
		end
	end




end



skynet.start(function()


	log_agent = skynet.uniqueservice "logcenter/logagent"

	-- If you want to fork a work thread , you MUST do it in CMD.login
	skynet.dispatch("lua", function(session, source, command, ...)
		local f = assert(CMD[command])
		if session ~= 0 then
			skynet.ret(skynet.pack(f(...)))
		else
			f(... )
		end
	end)

	skynet.dispatch("client", function(_,_, data)
		--log.d(TAG,"recv data[%s]",data)
		skynet.ret(do_request(data))
	end)


	--心跳包检测
	skynet.fork(function (  )
		while true do
			skynet.sleep(HEART_TIME)
			heart_check()
		end
	end)

end)